package top.gokzzz.common.utils;

import java.util.Map;
import java.util.Random;

/**
 * 字符串 工具類
 *
 * @author Gok
 * @version 1.2
 */
public class StrUtil {

    /**
     * 是否為空
     *
     * @param str 字符串
     * @return boolean
     */
    public static boolean isEmpty(String str) {
        return str == null || str.isEmpty();
    }


    /**
     * 是否不為空
     *
     * @param str 字符串
     * @return boolean
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    /**
     * 去除空白符號，String.trim() 加強版
     *
     * @param str str
     * @return {@link String }
     */
    public static String trim(String str) {
        String result;
        if (str == null) {
            result = null;
        } else {
            int length = str.length();
            int start = 0;
            int end = length;
            while ((start < end) && (isBlankChar(str.charAt(start)))) {
                start++;
            }
            while ((start < end) && (isBlankChar(str.charAt(end - 1)))) {
                end--;
            }
            if ((start > 0) || (end < length)) {
                result = str.substring(start, end);
            } else {
                result = str;
            }
        }
        return result;
    }

    /**
     * 判斷是否是空白字符
     *
     * @param c 字符
     * @return boolean
     */
    public static boolean isBlankChar(char c) {
        return isBlankChar((int) c);
    }

    /**
     * 判斷是否是空白字符
     *
     * @param c 字符
     * @return boolean
     */
    public static boolean isBlankChar(int c) {
        return Character.isWhitespace(c)
                || Character.isSpaceChar(c)
                || c == '\ufeff'
                || c == '\u202a'
                || c == '\u0000'
                || c == '\u3164'
                || c == '\u2800'
                || c == '\u180e';
    }

    /**
     * 判斷是否相同<br/>
     *
     * @param cs1 cs1
     * @param cs2 cs2
     * @return boolean
     */
    public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
        if (cs1 == cs2) {
            return true;
        }
        if (cs1 == null || cs2 == null) {
            return false;
        }
        if (cs1.length() != cs2.length()) {
            return false;
        }
        if (cs1 instanceof String && cs2 instanceof String) {
            return cs1.equals(cs2);
        }
        final int length = cs1.length();
        for (int i = 0; i < length; i++) {
            if (cs1.charAt(i) != cs2.charAt(i)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 文本內容字符串變量替換（替換字符默認 {param} ）
     * <p/>
     * 一般的場景也够用了, 時間複雜度：O(n)
     *
     * @param text   文本
     * @param params 替換參數變量
     * @return {@link String }
     */
    public static String format(String text, Map<String, Object> params) {
        return format(text, params, '{', '}');
    }


    /**
     * 文本內容字符串變量替換
     * <p/>
     * 一般的場景也够用了, 時間複雜度：O(n)
     *
     * @param text        文本
     * @param params      替換參數變量
     * @param startSymbol 開始字符，eg: '{'
     * @param endSymbol   結束字符，eg: '}'
     * @return {@link String }
     */
    public static String format(String text, Map<String, Object> params,
                                char startSymbol, char endSymbol) {
        StringBuilder stringBuilder = new StringBuilder();

        // 用於追踪未處理文本的開始位置
        int startIndex = 0;
        // 用於記錄上一次 startSymbol 的位置
        int braceOpenIndex = -1;

        for (int i = 0; i < text.length(); i++) {
            if (text.charAt(i) == startSymbol) {
                if (braceOpenIndex == -1) {
                    stringBuilder.append(text, startIndex, i);
                    braceOpenIndex = i;
                }
            } else if (text.charAt(i) == endSymbol) {
                if (braceOpenIndex != -1) {
                    // 提取鍵名稱，從 startSymbol 到 endSymbol 之間的內容
                    String key = text.substring(braceOpenIndex + 1, i);
                    // 根據 key 拿到對應的 value
                    Object value = params.get(key);
                    if (value != null) {
                        stringBuilder.append(value);
                    } else {
                        // 如果沒有對應的值，將整個佔位符保留在結果中
                        stringBuilder.append(text, braceOpenIndex, i + 1);
                    }
                    // 重置 startSymbol 的位置
                    braceOpenIndex = -1;
                    // 更新未處理文本的開始位置
                    startIndex = i + 1;
                }
            }
        }

        // 將最後一段未處理的文本添加到結果中
        if (startIndex < text.length()) {
            stringBuilder.append(text.substring(startIndex));
        }

        return stringBuilder.toString();
    }

    /**
     * 生成隨機字符串
     *
     * @param length      生成字符串的長度
     * @param randomModes 隨機模式
     * @return 隨機生成的字符串
     */
    public static String random(int length, RandomMode... randomModes) {
        if (randomModes.length == 0) {
            throw new IllegalArgumentException("At least one random mode must be provided.");
        }
        StringBuilder characterSet = new StringBuilder();

        for (RandomMode mode : randomModes) {
            characterSet.append(mode.getCharacterSet());
        }

        Random random = new Random();
        StringBuilder randomString = new StringBuilder(length);

        // 生成隨機字符串
        for (int i = 0; i < length; i++) {
            int index = random.nextInt(characterSet.length());
            randomString.append(characterSet.charAt(index));
        }

        return randomString.toString();
    }

    /**
     * 查看指定字符串是否包含字符串列表中任意一個
     *
     * @param str     指定字符串
     * @param strList 字符串列表
     * @return boolean
     */
    public static boolean containsAny(String str, String... strList) {
        if (isEmpty(str) || CollUtil.isEmpty(strList)) {
            return false;
        }

        for (String s : strList) {
            if (s != null && str.contains(s)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 隨機模式
     */
    public enum RandomMode {
        /**
         * 大寫字母
         */
        UPPERCASE_ALPHABET("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
        /**
         * 小寫字母
         */
        LOWERCASE_ALPHABET("abcdefghijklmnopqrstuvwxyz"),
        /**
         * 數字
         */
        NUMERIC("0123456789"),
        /**
         * 特殊字符
         */
        SPECIAL_CHARACTERS("!@#$%^&*()_+[]{}|;:,.<>?");

        private final String characterSet;

        RandomMode(String characterSet) {
            this.characterSet = characterSet;
        }

        public String getCharacterSet() {
            return characterSet;
        }
    }
}
